home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
17 Bit Software 3: The Continuation
/
17-Bit_The_Continuation_Disc.iso
/
amigan
/
amigan 15
/
clicktofront
/
clicktofront.asm
< prev
next >
Wrap
Assembly Source File
|
1994-01-27
|
13KB
|
476 lines
;ClickToFront V1.1 Copyright 1987 Bryce Nesbitt. Unlimited, revokable, free,
;non-exclusive licence hereby granted to any sentient being to use or abuse
;this code in any way whatsoever provided that this and any other copyright
;notices remain fully attached and are reproduced in any simultaneously
;distributed printed matter and with the exception that, without prior
;written permission, it not be utilized by any entity that has been commonly
;referred to as Robert W. Skyles, Skyles Electric Works, Jim Drew, Regie
;Warren or any organization founded by, controlled, employing or profiting
;any such entity, it's offspring or spouses. FISH use ok. Author
;correspondence, bug or stupidity reports may be directed to:
; 1712 Marin Ave.
; Berkeley, Ca 94707-2902
; bryce@cogsci.berkeley.EDU -or- ucbvax!cogsci!bryce
;"(almost) as seen in Transactor magazine".
;
;USAGE
; CLI - ClickToFront
; WB - Brings up requester, choose Install or Cancel
;
; A click into any part of any window works as normal.
; A double click brings it to the front. How handy!
;
; !!! In order to prevent false activation, lower the !!!
; !!! double-click sensitvity from preferences. !!!
;
;BUGS
; No provisions for un-install. The only way I can think to do this would
;be to add a handler at priority 52, then search the chain downward for a
;handler with name ClickToFront. This seems like a kludge.
; This program is NOT Intuition. This makes certain things more difficult.
;A test should be made that both clicks are over the same window. If some,
;kind Intuition() hacker has a way...
; No longer brings screens to the front.
; Proper size when assembled with Metacomco and Blink'ed with NODEBUG
; is 956 bytes.
;
**************
NOLIST
INCLUDE 'exec/types.i'
INCLUDE 'exec/memory.i'
INCLUDE 'exec/interrupts.i'
INCLUDE 'exec/io.i'
; INCLUDE 'exec/tasks.i'
ThisTask EQU $114
INCLUDE 'libraries/dosextens.i'
INCLUDE 'devices/inputevent.i'
INCLUDE 'devices/input.i'
; INCLUDE 'intuition/intuitionbase.i'
ib_ActiveWindow EQU $34
ib_ActiveScreen EQU $38
ib_FirstScreen EQU $3C
;
;What follows is a non-standard extension that eliminates the need to link
;with the HUGE amiga.lib file.
;
;INCLUDE 'lib/exec_lib.i'
;INCLUDE 'lib/intuition_lib.i'
LIST
jsrlib macro
xref _LVO\1
jsr _LVO\1(a6)
endm
jmplib macro
xref _LVO\1
jmp _LVO\1(a6)
endm
********************
CODE
startup: move.l 4,a6
move.l ThisTask(a6),a5
moveq #0,d0 ;Set zero for later
move.l pr_CLI(a5),d1 ;Pointer to CLI only structure
bne.s fromCLI ;If not zero, then save a zero...
;
; If called from Workbench a message will be sent. This waits for it,
; and saves it's pointer to be returned to Workbench later.
;
lea.l pr_MsgPort(a5),a0
jsrlib WaitPort
lea.l pr_MsgPort(a5),a0
jsrlib GetMsg ;Message pointer in D0
fromCLI move.l d0,-(a7) ;Save message for later...
******************************** [A6=ExecBase][a5=this task]
failcode equr d7
Ibase equr d6
portsave equr a5
IOReqsave equr a4
moveq #20,failcode ;Default code
;---Prepare StdIO---
bsr _CreatePortE ;[d0=Port]
beq ExitToDOS
move.l d0,portsave
bsr _CreateStdIOE ;[a1=IoRequest]
beq e_StdIO
move.l a1,IOReqsave
;---Open input.device---
moveq #0,d0 ;Unit
move.l d0,d1 ;Flags
lea.l devname(pc),a0
;[a1-IoRequest]
jsrlib OpenDevice ;[d0=zero if ok]
tst.l d0
bne e_Open
;---Open Intuition---
;Intuition will be opened, and the pointer given to the interrupt code
; Since the interrupt will still be installed after this task exits,
; intuition will be left open.
;
lea.l IntuiName(pc),a1
jsrlib OldOpenLibrary ;V1.0 Compatible :-)
move.l d0,Ibase ;(d)
beq e_Intui
tst.l (a7) ;check CLI flag on stack
beq.s DoIt ;always do it from CLI
move.l Ibase,a6
suba.l a0,a0
lea.l IText1(pc),a1
lea.l IText2(pc),a2
lea.l IText3(pc),a3
moveq #0,d0
moveq #0,d1
move.l #560,d2
moveq #68,d3
jsrlib AutoRequest
move.l 4,a6
tst.l d0 ;grumble, gritch, grrr...
bne.s DoIt
;---User said no, so pack our bags and go home--
move.l Ibase,a1
jsrlib CloseLibrary
bra.s Cancel
;---Copy Handler---
DoIt move.l #DownEnd-Start,d0
move.l #MEMF_PUBLIC+MEMF_CLEAR,d1
jsrlib AllocMem
move.l d0,a2 ;location of block
move.l d0,a1
tst.l d0
beq.s e_nomem
lea.l Start(pc),a0
moveq #((DownEnd-Start)/4)-1,d1 ;Length in LONGS-1
copylp move.l (a0)+,(a1)+ ;Copy handler to Public Memory
dbra d1,copylp ;68010 Loop mode!
;---Prepare IOReq with proper addresses---
lea.l Handlercode-Start(a2),a0 ;offset+memblock
move.l a0,IS_DATA(a2) ;unused
move.l a0,IS_CODE(a2) ;where code is
lea.l PopName-Start(a2),a0 ;set ascii name
move.l a0,LN_NAME(a2)
move.l Ibase,IBASE1+2-Start(a2) ;modify code
move.l Ibase,IBASE2+2-Start(a2) ;modify code
;---Send ADDHANDLER---
move.l IOReqsave,a1
move.w #IND_ADDHANDLER,IO_COMMAND(a1)
move.l a2,IO_DATA(a1)
;(IOReq in a1)
jsrlib DoIO ;d0=(IOReq-a0)
tst.l d0
bne.s e_DoIO ;bad<>0. Forget the memory...
Cancel moveq #0,d7
e_nomem
e_DoIO
e_Intui move.l IOReqsave,a1
jsrlib CloseDevice
e_Open move.l IOReqsave,a1
bsr _DeleteStdIOE
e_StdIO move.l portsave,a1
bsr _DeletePortE
tst.l failcode
beq.s ExitToDOS
;-- There can be only one reason why we failed (knock on formica) --
;-- and that is lack of memory. Unless you have a better idea... --
move.l ThisTask(a6),a1
moveq #ERROR_NO_FREE_STORE,d0
move.l d0,pr_Result2(a1)
******************************* (a7)+=message d7=return code a6=exec
ExitToDOS: move.l (a7)+,d2
beq.s NotWB ;If saved pointer is zero, exit to CLI...
;
; Return the startup message to the parent Workbench tool. The forbid
; is needed so workbench can't UnLoadSeg() the code too early.
;
jsrlib Forbid
move.l d2,a1 ;message pointer
jsrlib ReplyMsg
NotWB move.l failcode,d0 ;Set "failat" code
rts
;**** exec_support/CreatePort ***
;
; port=_CreatePort()
; d0
;
;FUNCTION: Create a nameless message port with a 0 priority.
; (exec/ports.i)
;RESULT: The port pointer or Z=1 if an error occured.
;REGISTERS: a6 is destroyed unless _CreatePortE is called,
; in which case a6 must contain ExecBase.
;EXAMPLE:
; moveq #3,d0 ;Set Priority
; jsr _CreatePort
; beq.s noport ;Not enough memory or signals
;
;xref _CreatePort
;xref _CreatePortE
;_CreatePort move.l 4,a6
_CreatePortE: move.l a2,-(a7)
move.l #MEMF_PUBLIC+MEMF_CLEAR,d1
moveq #MP_SIZE,d0
jsrlib AllocMem
move.l d0,a2
tst.l d0
beq.s cp_nomemory
moveq #-1,d0
jsrlib AllocSignal ;d0=return
moveq #-1,d1
cmp.l d0,d1 ;-1 indicates bad signal
bne.s cp_sigok
move.l a2,a1
moveq #MP_SIZE,d0
jsrlib FreeMem
cp_nomemory moveq #0,d0 ;set z=1
bra.s cp_xit
cp_sigok move.b d0,MP_SIGBIT(a2)
move.b #PA_SIGNAL,MP_FLAGS(a2)
move.b #NT_MSGPORT,LN_TYPE(a2)
clr.b LN_PRI(a2)
move.l ThisTask(a6),MP_SIGTASK(a2)
lea.l MP_MSGLIST(a2),a0 ;Point to list header
NEWLIST a0 ;Init new list macro
move.l a2,d0
cp_xit move.l (a7)+,a2 ;cc's NOT affected
rts
;**** exec_support/DeletePort ***
;
;_DeletePort(port)
; a1
;
;FUNCTION: Deletes the port by first setting some
; fields to illegal values then calling FreeMem.
;RESULT: none
;REGISTERS: a6 is destroyed unless _DeleteStdIOE is called,
; in which case a6 must contain ExecBase.
;
;xref _DeletePort
;xref _DeletePortE
;_DeletePort move.l 4,a6
_DeletePortE: move.l a1,-(a7)
moveq #-1,d0
move.b d0,LN_TYPE(a1)
move.l d0,MP_MSGLIST+LH_HEAD(a1)
moveq #0,d0 ;Clear upper 3/4 of d0
move.b MP_SIGBIT(a1),d0
jsrlib FreeSignal
move.l (a7)+,a1
moveq #MP_SIZE,d0
jmplib FreeMem
;
;ioStdReq=CreateStdIO(ioReplyPort)
; a1 d0
;
;Function: Allocate a IoRequest block of standard size.
;Example: move.l MyPort,d0
; jsr _CreateStdIO
; beq.s badnews
;
;xref _CreateStdIOE
;xref _CreateStdIO
;_CreateStdIO move.l 4,a6
_CreateStdIOE: move.l d0,-(a7)
moveq #IOSTD_SIZE,d0
move.l #MEMF_PUBLIC+MEMF_CLEAR,d1
jsrlib AllocMem
move.l d0,a1
tst.l d0
beq.s nomem
move.b #NT_MESSAGE,LN_TYPE(a1)
move.l (a7)+,MN_REPLYPORT(a1)
nomem rts
;*** exec_support/DeleteStdIO ***
;
;_DeleteStdIO(ioStdReq)
; a1
;
;FUNCTION: Deletes an ioStdReq by setting some
; fields to illegal values then calling FreeMem.
;RESULT: none
;REGISTERS: a6 is destroyed unless _DeleteStdIOE is called,
; in which case a6 must contain ExecBase.
;
;xref _DeleteStdIO
;xref _DeleteStdIOE
;_DeleteStdIO move.l 4,a6 ;Get ExecBase
_DeleteStdIOE: moveq #-1,d0 ;Set fields to illegal value
move.b d0,LN_TYPE(a1)
move.l d0,IO_DEVICE(a1)
move.l d0,IO_UNIT(a1)
moveq #IOSTD_SIZE,d0
jmplib FreeMem
IText1: dc.b 0,1,1,0 ;pens, drawmode and filler
dc.w 20,6 ;XY
dc.l 0 ;NULL for default font
dc.l ITextText1 ;pointer to text
dc.l IText1b ;next IntuitText structure
IText1b dc.b 0,1,1,0
dc.w 20,17
dc.l 0
dc.l ITextText1b
dc.l 0
IText2: dc.b 0,1,1,0
dc.w 6,3
dc.l 0
dc.l ITextText2
dc.l 0
IText3: dc.b 0,1,1,0
dc.w 6,3
dc.l 0
dc.l ITextText3
dc.l 0
ITextText1: dc.b 'ClickToFront installer v1.1. '
dc.b $a9,'1987 Bryce Nesbitt',0
ITextText1b dc.b 'Double-clicking will bring '
ITextText1c dc.b 'any window to the front',0
ITextText2: dc.b 'Install',0
ITextText3: dc.b 'Cancel',0
IntuiName: dc.b 'intuition.library',0
devname: dc.b 'input.device',0
;-------------------------------
cnop 0,4 ;LONG word align
Start:
ints: ;This is an interrupt structure (exec/interrupts.i)
;since it will be referenced by an interrupt it MUST be
;copied into PUBLIC memory. (All memory that will be used
;by interrupts or other tasks must be PUBLIC.)
dc.l 0 ;succ
dc.l 0 ;pred
dc.b 0 ;type
dc.b 51 ;Priority (One step higher than Intuition)
dc.l 0 ;Name
dc.l 0 ;Data
dc.l 0 ;Code
inte
;When the handler is entered a0 will point to a linked list of input
; events of the type defined in the incude file (devices/inputevent.i)
; When done mangling the input stream it returns a new pointer in d0
;Note: All references to (a0) below refer to ie_NextEvent(a0). The
; offeset equates to zero and was eliminated for effeciency.
Handlercode: move.l a0,d0 ;Save pointer to start of chain
cmpi.w #$0200,ie_Class(a0)
;Compare class AND subclass. $0200 is a combination of IECLASS_RAWMOUSE for
;ie_Class and IECLASS_NULL for ie_SubClass (it checks two BYTEs at once).
beq.s hurdle1
move.l (a0),d1 ;Get {ie_NextEvent} pointer
bne.s MoreEvents ;If any...
rts ;exit (with no changes made)
hurdle1 move.l ie_Code(a0),d1 ;Code & Qualifier.
andi.w #%0011000000000000,d1
;
;Mask off the bits of the qualifier field that we do not care about. In this
; case that's all but the RIGHT and MIDDLE buttons, which may not be down.
cmpi.l #$00680000,d1
;
;The upper word of this comparison ($0068) is the RAWMOUSE code for LBUTTON
; the lower is the match for the qualifier.
beq.s CheckClick
KeepLooking move.l (a0),d1 ;See above...
bne.s MoreEvents ;See above...
rts ;exit (no changes)
;
;MoreEvents handles the case where several events may be linked and
; can extract one of them from the middle.
MoreEvents ;move.l a0,a1 ;Temporary for unlinking
move.l d1,a0 ;Look here next...
cmpi.w #$0200,ie_Class(a0)
bne.s KeepLooking
move.l ie_Code(a0),d1
andi.w #%0011000000000000,d1
cmpi.l #$00680000,d1
bne.s KeepLooking
;
;Don't unlink the event, that would cause problems.
;
CheckClick movem.l a6/a1/d3/d2/d0,-(a7)
move.l a0,-(a7)
IBASE2 move.l #-1,a6 ;Self-modifying-> Intuitionbase
move.l TimeSave+0(pc),d0
move.l TimeSave+4(pc),d1
move.l ie_TimeStamp+0(a0),d2
move.l ie_TimeStamp+4(a0),d3
jsrlib DoubleClick
move.l (a7)+,a0
lea.l TimeSave+0(pc),a1
move.l ie_TimeStamp+0(a0),(a1)+
move.l ie_TimeStamp+4(a0),(a1)+
tst.l d0
movem.l (a7)+,d0/d2/d3/a1/a6 ;cc's not
beq.s KeepLooking
;[d0-short input]
;The pointer to the currently active Screen and Windows are available at a
; positive offset from the Intuition base pointer. These will be brought
; to the front. Note that it may not be proper under the Amiga system to
; do this in the actual handler. It may be safer to have another task
; lying around in the background to do the actual work. The description
; of the Intuition WindowToFront commands indicates that it will not take
; effect until the NEXT input event, which (of course) will not happen
; until this one exits. Now, if Intuition was a device...
;
tofront: movem.l a6/d0,-(a7)
IBASE1 move.l #-1,a6 ;Self-modifying-> Intuitionbase
moveq #0,d0
jsrlib LockIBase ;Lock before reading any private
move.l d0,-(a7) ;Intuition structures
;move.l ib_ActiveScreen(a6),d0 ;Uncomment to bring screen
;beq.s iinoscreen ;to front also
;move.l d0,a0
;jsrlib ScreenToFront
;move.l ib_ActiveScreen(a6),d0 ;Garbage, forget it
;beq.s inoscreen
;move.l d0,a0
;lea.l MouseYX(pc),a1
;move.l sc_MouseX(a0),d1
;cmp.l d1,(a1)
;bne.s imousemoved ;The mouse moved!! Don't do it!!
;move.l d1,(a1)
;jsrlib ScreenToFront
iinoscreen move.l ib_ActiveWindow(a6),d0
beq.s inowindow
move.l d0,a0
jsrlib WindowToFront
inowindow move.l (a7)+,a0
jsrlib UnlockIBase
movem.l (a7)+,d0/a6 ;d0 contains output pointer
rts
imousemoved ;move.l d1,(a1) ;Set last position
inoscreen ;move.l (a7)+,a0
;jsrlib UnlockIBase
;movem.l (a7)+,d0/a6
;rts ;don't bother with remaining chained events
PopName: dc.b 'ClickToFront',0
cnop 0,4 ;Pad out to Longword boundary
TimeSave: dc.l 0,0 ;longs on longs retain long
;MouseYX dc.l 0
DownEnd
END